using System;
using System.Net;
using System.Net.Quic;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;

namespace QUICRPC
{
    public class QuicClient
    {
        public async Task StartClient()
        {
            var connection = new QuicConnection(new IPEndPoint(IPAddress.Loopback, 5000), new QuicClientOptions
            {
                ApplicationProtocols = new[] { new QuicClientAlpnOption(Encoding.ASCII.GetBytes("myapp")) },
                DefaultStreamErrorCode = 0,
                DefaultCloseErrorCode = 0
            });

            await connection.ConnectAsync();
            Console.WriteLine("已连接到服务器");

            var stream = await connection.OpenOutboundStreamAsync();
            var name = "World";

            // 生成唯一 call id
            string callId = GenerateCallId();

            // 使用 RPC 调用获取在线客户端列表
            var rpcCallRequest = new QuicProtocol.Message { Type = QuicProtocol.MessageType.RpcCall, Data = $"{callId}:GetOnlineClients" };
            var rpcCallRequestBytes = rpcCallRequest.Serialize();
            await stream.WriteAsync(rpcCallRequestBytes);

            var clientsBuffer = new byte[1024];
            var clientsBytesRead = await stream.ReadAsync(clientsBuffer);
            var clientsResponse = QuicProtocol.Message.Deserialize(clientsBuffer.Take(clientsBytesRead).ToArray());
            if (clientsResponse != null) {
                // 验证 call id
                if (clientsResponse.Data.StartsWith(callId)) {
                    Console.WriteLine("在线客户端列表: " + clientsResponse.Data.Substring(callId.Length + 1));
                }
            }

            // 生成新的 call id
            callId = GenerateCallId();

            // 示例：调用其他客户端方法
            var rpcCallRequest = new QuicProtocol.Message { Type = QuicProtocol.MessageType.RpcCall, Data = $"{callId}:targetClient:methodName:parameters" };
            var rpcCallRequestBytes = rpcCallRequest.Serialize();
            await stream.WriteAsync(rpcCallRequestBytes);

            // 示例：发起文件传输请求
            string fileName = "example.txt";
            long fileSize = new System.IO.FileInfo(fileName).Length;
            // 生成新的 call id
            callId = GenerateCallId();
            var fileTransferRequest = new QuicProtocol.Message { Type = QuicProtocol.MessageType.FileTransferRequest, Data = $"{callId}:{fileName}:{fileSize}" };
            var fileTransferRequestBytes = fileTransferRequest.Serialize();
            await stream.WriteAsync(fileTransferRequestBytes);

            // 接收文件传输响应
            var fileResponseBuffer = new byte[1024];
            var fileResponseBytesRead = await stream.ReadAsync(fileResponseBuffer);
            var fileResponse = QuicProtocol.Message.Deserialize(fileResponseBuffer.Take(fileResponseBytesRead).ToArray());
            if (fileResponse != null && fileResponse.Type == QuicProtocol.MessageType.FileTransferAccept) {
                // 验证 call id
                if (fileResponse.Data.StartsWith(callId)) {
                    // 开始发送文件数据
                    using (var fileStream = new System.IO.FileStream(fileName, System.IO.FileMode.Open)) {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0) {
                            var fileDataMessage = new QuicProtocol.Message { Type = QuicProtocol.MessageType.FileTransferData, Data = System.Convert.ToBase64String(buffer, 0, bytesRead) };
                            var fileDataBytes = fileDataMessage.Serialize();
                            await stream.WriteAsync(fileDataBytes);
                        }
                    }
                }
            }

            var rpcCallBuffer = new byte[1024];
            var rpcCallBytesRead = await stream.ReadAsync(rpcCallBuffer);
            var rpcCallResponse = Encoding.UTF8.GetString(rpcCallBuffer, 0, rpcCallBytesRead);
            Console.WriteLine("RPC 调用响应: " + rpcCallResponse);
            var request = "HELO:" + name;
            var requestBytes = Encoding.UTF8.GetBytes(request);
            await stream.WriteAsync(requestBytes);

            var buffer = new byte[1024];
            var bytesRead = await stream.ReadAsync(buffer);
            var response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"收到服务器响应: {response}");

            await stream.DisposeAsync();
            await connection.DisposeAsync();
        }
    }
}